package com.msh.artascope.devcloud.service.wrapper;

import com.alibaba.fastjson.JSONObject;
import com.msh.artascope.devcloud.client.enums.biz.JenkinsBuildResultEnum;
import com.msh.artascope.devcloud.client.po.JenkinsConfigPo;
import com.msh.artascope.devcloud.client.po.ModuleBuildPo;
import com.msh.artascope.devcloud.client.po.ModulePo;
import com.msh.artascope.devcloud.client.po.ModuleResourcePo;
import com.msh.artascope.devcloud.client.po.ProjectPo;
import com.msh.artascope.devcloud.client.po.RegisterConfigPo;
import com.msh.artascope.devcloud.service.client.JenkinsClient;
import com.msh.artascope.devcloud.service.define.DevCloudDef;
import com.msh.artascope.devcloud.service.model.vo.BuildLogVo;
import com.msh.artascope.devcloud.service.util.FreemarkerUtil;
import com.msh.frame.client.define.StringDef;
import com.msh.frame.client.exception.BizException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;

@Slf4j
@Component
@AllArgsConstructor
public class JenkinsWrapper {
  private final JenkinsClient jenkinsClient;


  public Boolean hasJob(JenkinsConfigPo configPo, String namespace, String projectName){
    try {
      JSONObject jobDetail = jenkinsClient.getJobDetail(configPo, namespace, projectName);
      if(null == jobDetail){
        return false;
      }
      return true;
    } catch (IOException e) {
      log.warn("removeJob error", e);
      throw BizException.build("删除任务失败");
    }
  }

  public void removeJob(JenkinsConfigPo configPo, String namespace, String projectName){
    try {
      if(hasJob(configPo, namespace, projectName)){
        jenkinsClient.removeJob(configPo, namespace, projectName);
      }
    } catch (IOException e) {
      log.warn("removeJob error", e);
      throw BizException.build("删除任务失败");
    }
  }

  /**
   * 通过 xml 创建job
   * @param namespace
   * @param projectName
   */
  public void createJob(JenkinsConfigPo configPo, String namespace, String projectName){
    String xml = FreemarkerUtil.replaceFtl(Collections.emptyMap(), "jenkins_job.ftl");
    try {
      jenkinsClient.createJob(configPo, namespace, projectName, xml);
    } catch (Exception e) {
      log.error("JenkinsWrapper createJob error", e);
      throw BizException.build("创建任务失败");
    }
  }


  public void build(JenkinsConfigPo jenkinsConfigPo, RegisterConfigPo registerConfigPo, String namespace, ProjectPo projectPo, ModulePo modulePo, ModuleBuildPo moduleBuildPo, ModuleResourcePo moduleResourcePo, String commitId){
    try {
      String projectName = projectPo.getName();
      JSONObject jobDetail = jenkinsClient.getJobDetail(jenkinsConfigPo, namespace, projectName);
      BizException.doThrowIfNull("无法获取job信息", jobDetail);
      String address = registerConfigPo.getAddress();
      int nextBuildNumber = jobDetail.getInteger("nextBuildNumber");
      String pullImageName = DevCloudDef.getDockerImage(address, modulePo.getName(), namespace,
          commitId, nextBuildNumber);
      moduleBuildPo.setBuildNum(nextBuildNumber);
      moduleBuildPo.setImageName(pullImageName);
      MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
      map.add("projectGitUrl", projectPo.getGitUrl());
      map.add("branch", moduleBuildPo.getBranch());
      map.add("moduleName", modulePo.getName());
      map.add("pullImageName", pullImageName);
      map.add("commandParam", moduleBuildPo.getCommandParam());
      map.add("pipelineName", moduleBuildPo.getPipelineName());
      map.add("scriptGitUrl", jenkinsConfigPo.getScriptGitUrl());
      map.add("scriptBranch", jenkinsConfigPo.getScriptBranch());
      if(null == moduleResourcePo){
        moduleResourcePo = new ModuleResourcePo();
        moduleResourcePo.setJavaArgs(StringDef.EMPTY);
      }
      map.add("javaArgs", moduleResourcePo.getJavaArgs());
      jenkinsClient.build(jenkinsConfigPo, namespace, projectPo.getName(), map);
    }catch (Exception e){
      log.error("JenkinsWrapper build error", e);
      throw BizException.build("构建失败");
    }

  }

  public String getAllBuildLog(JenkinsConfigPo configPo, String namespace, String projectName, Integer buildNum) {
    try {
      return jenkinsClient.log(configPo, namespace, projectName, buildNum);
    } catch (Exception e) {
      log.error("JenkinsWrapper getAllBuildLog error", e);
      throw BizException.build("获取日志失败");
    }
  }


  public BuildLogVo getBuildLog(JenkinsConfigPo configPo, String namespace, String projectName, Integer bufferOffset, Integer buildNum) {
    try {
      JSONObject detail = jenkinsClient.getJobBuildDetail(configPo, namespace, projectName, buildNum);
      if(null == detail){
        return null;
      }
      JenkinsClient.ConsoleLog buildLog = jenkinsClient.logInfo(configPo, namespace, projectName, buildNum, bufferOffset);
      JenkinsBuildResultEnum result = getBuildResult(detail.getString("result"));
      return new BuildLogVo().setLog(buildLog.getLog()).setBufferSize(buildLog.getCurrentBufferSize()).setHasMore(buildLog.getHasMoreData()).setResult(result.getDesc());
    } catch (Exception e) {
      log.error("JenkinsWrapper getBuildLog error", e);
      throw BizException.build("获取日志失败");
    }
  }

  private JenkinsBuildResultEnum getBuildResult(String result){
    if(null == result){
      return JenkinsBuildResultEnum.NULL;
    }else if("SUCCESS".equals(result)){
      return JenkinsBuildResultEnum.SUCCESS;
    }else if("FAILURE".equals(result)){
      return JenkinsBuildResultEnum.FAIL;
    }
    log.warn("jenkins buid result unKnow: {}", result);
    return JenkinsBuildResultEnum.UN_KNOW;
  }

  public JenkinsBuildResultEnum getBuildResult(JenkinsConfigPo configPo, String namespace, String projectName, Integer buildNum) throws UnsupportedEncodingException {
    JSONObject detail = jenkinsClient.getJobBuildDetail(configPo, namespace, projectName, buildNum);
    String result = null;
    if(null != detail){
      result = detail.getString("result");
    }
    return getBuildResult(result);
  }
}
